#define LOG_TAG    "app_user"
#include "app_user.h"

extern ADC_HandleTypeDef hadc1;
extern ADC_HandleTypeDef hadc2;

uint16_t adc_rec_buf[APP_ADC_CHANNLE_MAX][APP_ADC_DMA_REC_BUF_SIZE];
volatile uint32_t adc_cover_finished[APP_ADC_CHANNLE_MAX];
static uint32_t running_count = 0;
static uint32_t app_running_delay_tick_start;
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    if(hadc == &hadc1) {
        adc_cover_finished[0]++;
    }

    if(hadc == &hadc2) {
        adc_cover_finished[1]++;
    }
}

static void app_log_init(void)
{
    /* initialize EasyLogger */
    elog_init();
    /* set EasyLogger log format */
    elog_set_fmt(ELOG_LVL_ASSERT,  ELOG_FMT_ALL & ~(ELOG_FMT_T_INFO | ELOG_FMT_P_INFO));
    elog_set_fmt(ELOG_LVL_ERROR,   ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME);
    elog_set_fmt(ELOG_LVL_WARN,    ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME);
    elog_set_fmt(ELOG_LVL_INFO,    ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME);
    elog_set_fmt(ELOG_LVL_DEBUG,   ELOG_FMT_ALL & ~(ELOG_FMT_FUNC | ELOG_FMT_T_INFO | ELOG_FMT_P_INFO));
    elog_set_fmt(ELOG_LVL_VERBOSE, ELOG_FMT_ALL & ~(ELOG_FMT_FUNC | ELOG_FMT_T_INFO | ELOG_FMT_P_INFO));
    /* start EasyLogger */
    elog_start();

   log_i("SYS   CLOCK FREQUENCE = %d Mhz", HAL_RCC_GetSysClockFreq() / 1000000);
   log_i("HCLK  CLOCK FREQUENCE = %d Mhz", HAL_RCC_GetHCLKFreq() / 1000000);
   log_i("PCLK1 CLOCK FREQUENCE = %d Mhz", HAL_RCC_GetPCLK1Freq() / 1000000);
   log_i("PCLK2 CLOCK FREQUENCE = %d Mhz", HAL_RCC_GetPCLK2Freq() / 1000000);
}

#define APP_MAX_ADC_VALUE 3000
#define APP_MIN_ADC_VALUE 0
typedef struct {
    uint16_t midle_value;
    uint16_t max_value;
    uint16_t min_value;
    uint16_t value_to_1_percent_up;
    uint16_t value_to_1_percent_down;
} app_stick_control_t;
app_stick_control_t app_stick_control[APP_ADC_CHANNLE_MAX];

static void app_adc_init(void)
{
    uint32_t adc_value_sum = 0;
    uint32_t adc_value_avg = 0;
    uint16_t adc_value_temp = 0;
    uint32_t delay_count = 10;

    adc_cover_finished[0] = 0;
    adc_cover_finished[1] = 0;

    // channel 4
    HAL_ADC_Start_DMA(&hadc1, (uint32_t *)&adc_rec_buf[0][0], APP_ADC_DMA_REC_BUF_SIZE);
    HAL_Delay(10);

    do {
        if(adc_cover_finished[0]) {
            adc_cover_finished[0] = 0;

                for(uint32_t i = 0; i < APP_ADC_DMA_REC_BUF_SIZE; i++) {
                    adc_value_temp = (adc_rec_buf[0][i] + 50) / 100 * 100;
                    adc_value_sum += adc_value_temp;
                }
                adc_value_sum /= APP_ADC_DMA_REC_BUF_SIZE;
                adc_value_avg = (adc_value_sum + 50) / 100 * 100;
                log_d("sum = %d ->%d", adc_value_sum, adc_value_avg);
                app_stick_control[0].max_value = APP_MAX_ADC_VALUE;
                app_stick_control[0].min_value = APP_MIN_ADC_VALUE;
                app_stick_control[0].midle_value = adc_value_avg;
                app_stick_control[0].value_to_1_percent_up   = ((app_stick_control[0].max_value   - app_stick_control[0].midle_value)) / 50;
                app_stick_control[0].value_to_1_percent_down = ((app_stick_control[0].midle_value - app_stick_control[0].min_value))   / 50;
                log_i("adc 0 init--> mid: %d, up:%d, down:%d", app_stick_control[0].midle_value, app_stick_control[0].value_to_1_percent_up, app_stick_control[0].value_to_1_percent_down);
            
            delay_count = 0;
        } else {
            delay_count--;
            HAL_ADC_Start_DMA(&hadc1, (uint32_t *)&adc_rec_buf[0][0], APP_ADC_DMA_REC_BUF_SIZE);
            HAL_Delay(10);
        }

    } while(delay_count);

    HAL_ADC_Start_DMA(&hadc2, (uint32_t *)&adc_rec_buf[1][0], APP_ADC_DMA_REC_BUF_SIZE);
    HAL_Delay(10);

    // channle 5
    adc_value_sum = 0;
    adc_value_avg = 0;
    adc_value_temp = 0;
    delay_count = 10;
    do {
        if(adc_cover_finished[1]) {
            adc_cover_finished[1] = 0;

            for(uint32_t i = 0; i < APP_ADC_DMA_REC_BUF_SIZE; i++) {
                adc_value_temp = (adc_rec_buf[1][i] + 50) / 100 * 100;
                adc_value_sum += adc_value_temp;
            }
            adc_value_sum /= APP_ADC_DMA_REC_BUF_SIZE;
            adc_value_avg = (adc_value_sum + 50) / 100 * 100;
            log_d("sum = %d ->%d", adc_value_sum, adc_value_avg);
            app_stick_control[1].max_value = APP_MAX_ADC_VALUE;
            app_stick_control[1].min_value = APP_MIN_ADC_VALUE;
            app_stick_control[1].midle_value = adc_value_avg;
            app_stick_control[1].value_to_1_percent_up   = ((app_stick_control[1].max_value   - app_stick_control[1].midle_value)) / 50;
            app_stick_control[1].value_to_1_percent_down = ((app_stick_control[1].midle_value - app_stick_control[1].min_value))   / 50;
            log_i("adc 1 init--> mid: %d, up:%d, down:%d", app_stick_control[1].midle_value, app_stick_control[1].value_to_1_percent_up, app_stick_control[1].value_to_1_percent_down);
            delay_count = 0;
        } else {
            delay_count--;
            HAL_ADC_Start_DMA(&hadc2, (uint32_t *)&adc_rec_buf[1][0], APP_ADC_DMA_REC_BUF_SIZE);
            HAL_Delay(10);
        }

    } while(delay_count);

}

// 50% to 0°
void app_motor_angle_setting(uint32_t channel, uint32_t percent)
{
    uint32_t duty = 0;

    if(percent > 50) {
        duty = ANGLE_MIDDLE + (ANGLE_0_TO_90 * percent / 100);
    } else if(percent == 50){
        duty = ANGLE_MIDDLE;
    } else {
        duty = ANGLE_MIN + (ANGLE_0_TO_90 *  percent / 100);
    }

    if(duty < ANGLE_MIN) {
        duty = ANGLE_MIN;
    }

    if(duty > ANGLE_MAX) {
        duty = ANGLE_MAX;
    }

    log_d("motor[%d] percent = %d duty = %d", channel, percent, duty);
    drv_pwm_duty_set(channel, duty);
}

void app_stick_percent_calculate(uint8_t ch, uint16_t input)
{
    static uint8_t percent_last[2] = {0xff, 0xff};
    uint8_t percent = 0;
    if(input > app_stick_control[ch].midle_value) {
        percent = 50 + (input - app_stick_control[ch].midle_value) / app_stick_control[ch].value_to_1_percent_up;
    } else if(input == app_stick_control[ch].midle_value) {
        percent = 50;
    } else {
        percent = 50 - ((app_stick_control[ch].midle_value - input) / app_stick_control[ch].value_to_1_percent_down);
    }

    // log_d("percent: %d", percent);

    if(ch == 0) {
        if(percent_last[0] != percent) {
            percent_last[0] = percent;
            app_motor_angle_setting(TIM_CHANNEL_1, percent);
        }
    } else if(ch == 1) {
        if(percent_last[1] != percent) {
            percent_last[1] = percent;
            app_motor_angle_setting(TIM_CHANNEL_2, percent);
        }
    } else {

    }
}

void app_user_init(void)
{
    adc_cover_finished[0] = 0;
    adc_cover_finished[1] = 0;

	app_log_init();
    app_adc_init();
    drv_pwm_init();
    app_running_delay_tick_start = HAL_GetTick();
}

void app_run(void)
{
    // if(clock_time_exceed(app_running_delay_tick_start, RUNNING_INTERVAL)) {
    if(clock_time_exceed(app_running_delay_tick_start, 100)) {
        app_running_delay_tick_start = HAL_GetTick();
        // log_i("running.... :%d", running_count++);
        
        for(uint32_t i = 0; i < APP_ADC_CHANNLE_MAX; i++) {
            if(adc_cover_finished[i]) {
                    uint32_t adc_value_sum = 0;
                    uint16_t adc_value_temp = 0;
                    for(uint32_t j = 0; j < APP_ADC_DMA_REC_BUF_SIZE; j++) {
                        adc_value_temp = (adc_rec_buf[i][j] + 50) / 100 * 100;
                        adc_value_sum += adc_value_temp;
                        // log_i("adc[%d] = %d", i, adc_value_temp);
                    }
                    adc_value_sum /= APP_ADC_DMA_REC_BUF_SIZE;
                    app_stick_percent_calculate(i, adc_value_sum);
                adc_cover_finished[i] = 0;
            } else {
                if(i == 0) {
                    HAL_ADC_Start_DMA(&hadc1, (uint32_t *)&adc_rec_buf[0][0], APP_ADC_DMA_REC_BUF_SIZE);
                }

                if(i == 1) {
                    HAL_ADC_Start_DMA(&hadc2, (uint32_t *)&adc_rec_buf[1][0], APP_ADC_DMA_REC_BUF_SIZE);
                }
            }
        }
    }

}
